﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using COFE.Core;
using COFE.Core.Entry;
using COFE.Core.Utils;
using COFE.Core.Validater;

namespace COFE.Core
{
    public abstract class EntryListBase : PropertyHostBase<IEntryList>, IEntryList
    {
        #region Constructor

        protected EntryListBase(Guid id, string name, 
            IPropertyProvider primaryPropProvider = null)
            : base(primaryPropProvider)
        {
            _thisObj = this;
            _name = name;
            _id = id;
        }

        #endregion

        #region Methods

        public virtual void OnEntryListRenamed(string oldName, string newName)
        {
            _name = newName;
        }

        public override object[] GetSupportedProperty(
             PropertyRetrivalOptions options = PropertyRetrivalOptions.NotApplied,
             MatchMode matchMode = MatchMode.All,
             params IPropertyFilter[] filters)
        {
            IEnumerable<object> retVal = 
                new List<object>(COFEShared.SecondaryPropertyProviderManager
                    .GetSupportedProperty<IEntryList>(this));

            switch (options)
            {
                case PropertyRetrivalOptions.NotApplied:
                    retVal = retVal.Union(
                        base.GetSupportedProperty(options, matchMode, filters));
                    break;
                case PropertyRetrivalOptions.First:
                    retVal = retVal.Union(
                        (this.Entries.First() as IInternalFileSystemInfoExA)
                        .GetSupportedProperty());
                    break;
                case PropertyRetrivalOptions.Aggregate:
                    foreach (var entry in this.Entries)
                        retVal = retVal.Union((entry as IInternalFileSystemInfoExA)
                            .GetSupportedProperty());
                    break;
            }

            return retVal.TakeWhile((p) => FilterUtils2
                .MatchPropertyFilters(p, matchMode, filters)).ToArray();
        }

        public override PropertyPair GetProperty(object property,
            PropertyRetrivalOptions options = PropertyRetrivalOptions.NotApplied)
        {
            if (this.Entries.Any())
                switch (options)
                {
                    case PropertyRetrivalOptions.NotApplied:
                        if (base.IsPropertySupported(property, options))
                            return base.GetProperty(property, options);
                        break;
                    case PropertyRetrivalOptions.First:
                        var firstEntry = this.Entries.First().InternalProperties;
                        if (firstEntry.IsPropertySupported(property))
                            return firstEntry.GetProperty(property);
                        break;
                    case PropertyRetrivalOptions.Aggregate:
                        var firstEntry1 = this.Entries.First().InternalProperties;
                        if (firstEntry1.IsPropertySupported(property))
                        {
                            IEnumerable<object> values =
                                from e in this.Entries
                                where e.InternalProperties.IsPropertySupported(property)
                                select e.InternalProperties.GetProperty(property).Value;
                            Type defType = PropertyTypeExtension.GetDefaultPropertyType(property);

                            switch (defType.Name)
                            {
                                case "Int16": return new PropertyPair(property, values.Sum(o => (Int16)o));
                                case "Int32": return new PropertyPair(property, values.Sum(o => (Int32)o));
                                case "Int64": return new PropertyPair(property, values.Sum(o => (Int64)o));
                                case "String": return new PropertyPair(property, String.Join(",", values));
                            }
                        }
                        break;
                }

            var retVal = COFEShared.SecondaryPropertyProviderManager
                .GetProperty<IEntryList>(this, property);
            if (retVal != null)
                return retVal;

            throw new NotSupportedException();
        }

        #endregion

        #region Data
        
        private string _name;
        private Guid _id;

        #endregion

        #region Public Properties

        public virtual StatusType Status { get; protected set; }        
        public string Name { get { return _name; } set { OnEntryListRenamed(_name, value); } }
        public Guid Id { get { return _id; } }
        
        public abstract IEnumerable<IFileSystemInfo> Entries { get; }
    
        #endregion     
    }
}
